﻿/// <reference path="../jquery-1.4.4.js" />
/// <reference path="../jquery-1.4.4-vsdoc.js" />

/*!  
** Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
** Dual licensed under the MIT and GPL licenses:
** http://www.opensource.org/licenses/mit-license.php
** http://www.gnu.org/licenses/gpl.html
** 
**----------------------------------------------------------------
** title        : DJME Menu
** version   : 2.0.1
** modified: 2011-5-21
** depends:
**    jquery.ui.core.js
**    jquery.ui.widget.js
**----------------------------------------------------------------
*/

(function ($) {
    $.widget("ui.dnamenu", {
        options: {
            type: "horizontal", //horizontal  vertical
            topMenuClass: null,
            topItemClass: null,
            topItemHoverClass: null, // "ui-state-active",
            topItemSelectedClass: null, // "ui-state-active",
            subMenuClass: null, //"ui-widget-content",
            subMenuItemClass: null, // "ui-state-default",
            subMenuItemHoverClass: null, // "ui-state-active",
            open: null,
            close: null,
            itemClick: null,
            skateBoard: false,
            skateBoardClass: "ui-state-highlight",
            showEffect: "slide", //'blind', 'clip', 'drop', 'explode', 'fold', 'puff', 'slide', 'scale', 'size', 'pulsate'
            hideEffect: "slide", //'blind', 'clip', 'drop', 'explode', 'fold', 'puff', 'slide', 'scale', 'size', 'pulsate'
            contextElement: null,
            delay: 100,
            opacity: 1
        },
        _create: function () {
            var self = this, opts = this.options, el = this.element, eventPrefix = this.widgetEventPrefix,
            _topItems = $(">ul>.d-menu-item", el);
            el.addClass("d-menu");

            if ($.fn.bgiframe)
                el.bgiframe();

            if (opts.open)
                el.bind(eventPrefix + "open", opts.open);

            if (opts.close)
                el.bind(eventPrefix + "close", opts.close);

            if (opts.itemClick)
                el.bind(eventPrefix + "itemclick", opts.itemClick);

            if (_topItems.length) {
                _topItems.addClass("d-top-menu-item");
                if (opts.topItemClass) _topItems.addClass(opts.topItemClass);

                //_topItems.each(function (i, n) { $(n).data("top", true); });

                if (opts.type == "horizontal") {
                    //_topItems.css({ "float": "left" });
                    $(">ul", el).addClass("d-horizontal");
                }
                else {
                    $(">ul", el).addClass("ui-helper-reset d-vertical");
                    if (opts.type == "context")
                        el.addClass("d-context-menu");
                }

                _topItems.css({
                    "position": "relative"
                });
            }

            var _allItems = $(".d-menu-item:not(.d-state-disabled)", el);
            $(document).click(self._delegate(self, self._ondocumentclick));

            if (_allItems.length) {
                _allItems.live("mouseenter", self._delegate(self, self._onmouseenter))
                             .live("mouseleave", self._delegate(self, self._onmouseleave))
                             .live("click", self._delegate(self, self._onitemclick));
                //.addClass("ui-helper-reset");.live("click", function () { el.trigger(eventPrefix + "click", this); })

                if (opts.subMenuItemClass) {
                    _allItems.each(function (i, n) {
                        $(n).find(".d-menu-item").addClass(opts.subMenuItemClass);
                    });
                }

                var $ul = $(".d-menu-container", _allItems);

                if ($ul.length) {
                    $ul.each(function (i, n) {
                        var _c = $(n);
                        _c.css({
                            "width": _c.outerWidth(true) + "px"
                        });
                    });
                    $ul.hide();
                }

                if ((opts.skateBoard) && (opts.type == "horizontal")) {
                    this.skated = $("<li />").addClass("d-menu-skateitem")
                                                            .appendTo($(">ul", el))
                                                            .css({ position: "absolute" });
                    if (opts.skateBoardClass)
                        this.skated.addClass(opts.skateBoardClass);
                    var $fixedEl = el.children(".d-state-selected").length ? el.children(".d-state-selected") : $(_topItems[0]);
                    if ($fixedEl.length)
                        this._fixedTo($fixedEl);
                }
            }
            if (opts.type == "context")
                el.hide();
        },
        dropdown: function (element) {
            if (element) {
                var $el = $(element),
                x = ($el.position().left + $el.outerWidth(true)) - this.element.outerWidth(true),
                y = $el.position().top + $el.outerHeight(true);
                this.showMenu(x > 0 ? x : 0, y > 0 ? y : 0);
            }
        },
        closeMenu: function () {
            var self = this;
            if (!this.element.hasClass("d-state-open")) return;
            clearTimeout(this.element.data("contextTimer"));
            this.element.data("contextTimer", setTimeout(function () {
                self.element.removeClass("d-state-open");
                self.element.hide(self.options.hideEffect, { direction: "up" }, self.options.delay);
            }, 100));
        },
        showMenu: function (x, y) {
            var self = this;
            if (this.element.hasClass("d-state-open"))
                this.closeMenu();

            clearTimeout(this.element.data("contextTimer"));
            this.element.data("contextTimer", setTimeout(function () {
                self.element.css({
                    left: x + "px",
                    top: y + "px"
                });
                self.element.show(self.options.showEffect, { direction: "up" }, self.options.delay);
                self.element.addClass("d-state-open");
            }, 100));
        },
        _triggerEvent: function (eventName, eventArgs) {
            this.element.trigger(this.widgetEventPrefix + eventName, eventArgs);
        },
        _delegate: function (context, handler) {
            return function (e) {
                handler.apply(context, [e, this]);
            };
        },
        _onitemclick: function (e, element) {
            e.stopPropagation();
            if (this.element.hasClass("d-context-menu"))
                this.closeMenu();

            this._triggerEvent("itemclick", element);
        },
        _ondocumentclick: function (e, element) {
            var self = this;
            try {
                if (this.element.hasClass("d-context-menu")) {
                    if (this.element.hasClass("d-state-open"))
                        this.closeMenu();
                }

                if (self._contains(this.element, e.target))
                    return;

                $(this.element).children(".d-menu-item").each(function (i, item) {
                    //if ($(item).data("open"))
                    if ($(item).hasClass("d-state-open"))
                        self.close($(item));
                });
            }
            catch (e) {
                return;
            }
        },
        _fixedTo: function (element) {
            if (this.skated && element.parent().hasClass("d-horizontal")) {
                var _l = element.position().left, _w = element.outerWidth(false) - 2;
                this.skated.css({
                    left: _l,
                    width: _w
                })
                .data("origLeft", _l)
                .data("origWidth", _w);
            }
        },
        _parkTo: function (element) {
            if (this.skated && element.parent().hasClass("d-horizontal")) {
                this.skated.stop().animate({
                    left: this.skated.data("origLeft"),
                    width: this.skated.data("origWidth")
                });
            }
        },
        _slideTo: function (element) {
            if (this.skated && element.parent().hasClass("d-horizontal")) {
                this.skated.stop().animate({
                    left: element.position().left,
                    width: element.outerWidth(false) - 2
                });
            }
        },
        _onmouseenter: function (e, element) {
            var $li = $(element), opts = this.options;

            if ($li.hasClass("d-state-disabled")) return;

            if (opts.skateBoard) this._slideTo($li);

            if ($li.hasClass("d-state-open")) return;
            // if ($li.data("open")) return;

            // if ($li.data("top"))
            if ($li.hasClass("d-top-menu-item"))
                $li.addClass(opts.topItemHoverClass);
            else
                $li.addClass(opts.subMenuItemHoverClass);

            if (!this._contains(element, e.relatedTarget)) {
                this._triggerEvent("open", $li);
                //$li.data("open", true);
                $li.addClass("d-state-open");
                this.open($li);

                var parentItem = $li.parent().closest(".d-menu-item")[0];
                if (parentItem && !$.contains(parentItem, e.relatedTarget))
                    this._onmouseenter(e, parentItem);
            }
        },
        _onmouseleave: function (e, element) {
            var $li = $(element), opts = this.options;
            //if (!$li.data("open")) return;
            if (!$li.hasClass("d-state-open")) return;

            if (opts.skateBoard) this._parkTo($li);

            //if ($li.data("top"))
            if ($li.hasClass("d-top-menu-item"))
                $li.removeClass(opts.topItemHoverClass);
            else
                $li.removeClass(opts.subMenuItemHoverClass);

            if (!this._contains(element, e.relatedTarget)) {
                this._triggerEvent("close", $li);
                //$li.data("open", false);
                $li.removeClass("d-state-open");
                this.close($li);

                var parentItem = $li.parent().closest(".d-menu-item")[0];
                if (parentItem && !$.contains(parentItem, e.relatedTarget))
                    this._onmouseleave(e, parentItem);
            }
        },
        _getDirectionOptions: function ($li) {
            var parent = $li.parent();
            return {
                direction: parent.hasClass("d-horizontal") ? "up" : "left"
            };
        },
        _contains: function (parent, child) {
            try {
                return $.contains(parent, child);
            } catch (e) {
                return false;
            }
        },
        _setMenuPosition: function ($li, target) {
            var parent = $li.parent();

            $(target).css({
                "position": "absolute",
                "left": 0 + "px",
                "z-index": 2000
            });

            tw = $(target).width(), sw = window.innerWidth, lpos = $li.position().left, lw = $li.outerWidth(true), cl = 0;
            cl = ((tw + lpos) > sw ? -(tw - lw) : 0);
            if (cl) $(target.css({ "left": cl + "px" }));

            if (!parent.hasClass("d-horizontal")) {
                $(target).css({
                    "top": "0px",
                    "left": $li.outerWidth() + "px",
                    "z-index": "5000"
                });
            }
        },
        _wrap: function (element) {
            if (!element.parent().hasClass('d-group-helper')) {
                element.show();
                var _w = element.outerWidth() + 5,
                _h = element.outerHeight();
                element.parent().css("position", "relative");
                element.wrap(
                             $('<div/>')
                             .addClass('d-group-helper')
                             .css({
                                 width: _w,
                                 height: _h
                             }));
            }
            return element.parent().css({ opacity: this.options.opacity });
        },
        open: function ($li) {
            var self = this;
            $($li).each(function (i, n) {
                var $item = $(n);
                clearTimeout($item.data("timer"));
                $item.data("timer", setTimeout(function () {
                    var $ul = $item.find(".d-menu-container:first");
                    if ($ul.length) {
                        var wrapper = self._wrap($ul);
                        self._setMenuPosition($item, wrapper);
                        wrapper.show(self.options.showEffect, self._getDirectionOptions($item), self.options.delay);
                    }
                }), 100);
            });
        },
        close: function ($li) {
            var self = this;
            $($li).each(function (i, n) {
                var $item = $(n);
                clearTimeout($item.data("timer"));
                $item.data("timer", setTimeout(function () {
                    var $ul = $item.find(".d-menu-container:first");
                    if ($ul.length) {

                        self._wrap($ul).hide(self.options.hideEffect, self._getDirectionOptions($item), self.options.delay);
                    }
                    $ul.find("ul").stop(false, true);
                }, 100));
            });
        },
        addItems: function () { },
        addItem: function (oParent, oItem) {
            var _parent = this._checkParent(oParent),
             _dom = $("<li/>").appendTo(_parent)
            $("<a/>").appendTo(_dom)
                                .attr("href", oItem.url ? oItem.url : "#")
                                .text(oItem.text ? oItem.text : "");
        },
        destroy: function () {
            this.element.unbind();
            $("li", this.element).unbind();
            $.Widget.prototype.destroy.call(this);
        }
    });
})(jQuery);
